﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using Painter3D.PhysicalSys;
using Painter3D.RenderSys;
using Painter3D.RenderSys.DebugDrawer;
using Painter3D.RenderSys.RenderObject;
using BulletSharp;
using RigidBody = Painter3D.PhysicalSys.RigidBody;

namespace Painter3D.Tool
{
    public static class QuickTool
    {
        static private Transform traget;
        static private Transform markT;
        static private Transform translateT;
        static private Transform rotateT;
        static private Transform scaleT;

        static VertexData translationMark;
        static VertexData rotationMark;
        static VertexData scaleMark;


        public enum ToolStateEnum
        {
            /// <summary>
            /// 鼠标点击物体只能完成选择
            /// </summary>
            Picker,
            /// <summary>
            /// 为鼠标点击的物体提供平移操作柄
            /// </summary>
            Translate,
            /// <summary>
            /// 为鼠标点击的物体提供旋转操作柄
            /// </summary>
            Rotate,
            /// <summary>
            /// 为鼠标点击的物体提供缩放操作柄
            /// </summary>
            Scale,
        }
        static private ToolStateEnum state;
        static public ToolStateEnum State
        {
            set
            {
                state = value;
                ChangeMark(state);
            }
            get
            {
                return state;
            }
        }
        /// <summary>
        /// 拾取鼠标点击的物体
        /// </summary>
        /// <returns>物体的transform,null则表明失败</returns>
        static public Transform PickObject()
        {
            Vector3 dif = Camera.scenceMainCamera.ScreenToWorld(InputManager.mouse.NormalizedPosition())
                - Camera.scenceMainCamera.Transform.position;
            BulletEngine.RayCastResult[] results = BulletEngine.RayCastAll(
                Camera.scenceMainCamera.Transform.position.Convert2BT(),
                (Camera.scenceMainCamera.Transform.position + dif * 20).Convert2BT());
            if (results != null)
            {
                foreach (var result in results)
                {
                    if (result.transform.IsTheChildOf(markT))
                    {

                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 准备标记物体，构建渲染对象。
        /// </summary>
        static public void Init()
        {
            if (!ModuleImporter.Load(@"F:\Painter3D\Resource\Module\TranslationMark.stl", Assimp.PostProcessSteps.Triangulate, out float[] positionT, out uint[] indexT))
            {
                throw new Exception("平移标签文件加载失败");
            }
            translationMark = new ElementVertexData(positionT, indexT);
            if (!ModuleImporter.Load(@"F:\Painter3D\Resource\Module\RotationMark.stl", Assimp.PostProcessSteps.Triangulate, out float[] positionR, out uint[] indexR))
            {
                throw new Exception("旋转标签文件加载失败");
            }
            rotationMark = new ElementVertexData(positionR, indexR);
            if (!ModuleImporter.Load(@"F:\Painter3D\Resource\Module\ScaleMark.stl", Assimp.PostProcessSteps.Triangulate, out float[] positionS, out uint[] indexS))
            {
                throw new Exception("缩放标签文件加载失败");
            }
            scaleMark = new ElementVertexData(positionS, indexS);

            markT = new Transform("Mark");

            translateT = new Transform("translateMark", markT);
            Transform newTransform = new Transform("X", Vector3.Zero, Quaternion.Identity, translateT);
            newTransform.AddRender(
                translationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(1, 0, 0, 1)))
                .layer.SetLayer("symbol");
            newTransform.AddComponent(new RigidBody(newTransform, new BoxShape(1.2f, 0.03f, 0.03f), RigidBody.RigidBodyTypeEnum.Kinematic));
            new Transform("Y", Vector3.Zero, Quaternion.FromEulerAngles(Vector3.UnitZ * MathHelper.PiOver2), translateT).AddRender(
                translationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 1, 0, 1)))
                .layer.SetLayer("symbol");
            new Transform("Z", Vector3.Zero, Quaternion.FromEulerAngles(-Vector3.UnitY * MathHelper.PiOver2), translateT).AddRender(
                translationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 0, 1, 1)))
                .layer.SetLayer("symbol");

            rotateT = new Transform("rotateMark", markT);
            new Transform("X", Vector3.Zero, Quaternion.Identity, rotateT).AddRender(
                rotationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(1, 0, 0, 1)))
                .layer.SetLayer("symbol");
            new Transform("Y", Vector3.Zero, Quaternion.FromEulerAngles(Vector3.UnitZ * MathHelper.PiOver2), rotateT).AddRender(
                rotationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 1, 0, 1)))
                .layer.SetLayer("symbol");
            new Transform("Z", Vector3.Zero, Quaternion.FromEulerAngles(-Vector3.UnitY * MathHelper.PiOver2), rotateT).AddRender(
                rotationMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 0, 1, 1)))
                .layer.SetLayer("symbol");

            scaleT = new Transform("scaleMark", markT);
            new Transform("X", Vector3.Zero, Quaternion.Identity, scaleT).AddRender(
                scaleMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(1, 0, 0, 1)))
                .layer.SetLayer("symbol");
            new Transform("Y", Vector3.Zero, Quaternion.FromEulerAngles(Vector3.UnitZ * MathHelper.PiOver2), scaleT).AddRender(
                scaleMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 1, 0, 1)))
                .layer.SetLayer("symbol");
            new Transform("Z", Vector3.Zero, Quaternion.FromEulerAngles(-Vector3.UnitY * MathHelper.PiOver2), scaleT).AddRender(
                scaleMark,
                new Material(ShaderManager.Find("SolidColor.glsl"))
                .WithValue("mainColor", new Vector4(0, 0, 1, 1)))
                .layer.SetLayer("symbol");
        }

        static private void ChangeMark(ToolStateEnum state)
        {
            switch (state)
            {
                case ToolStateEnum.Picker:
                    translateT.Enable = false;
                    rotateT.Enable = false;
                    scaleT.Enable = false;
                    break;
                case ToolStateEnum.Translate:
                    translateT.Enable = true;
                    rotateT.Enable = false;
                    scaleT.Enable = false;
                    break;
                case ToolStateEnum.Rotate:
                    translateT.Enable = false;
                    rotateT.Enable = true;
                    scaleT.Enable = false;
                    break;
                case ToolStateEnum.Scale:
                    translateT.Enable = false;
                    rotateT.Enable = false;
                    scaleT.Enable = true;
                    break;
            }
        }

        static public void OnUpdate()
        {
            if (InputManager.mouse.IsButtonDown(OpenTK.Input.MouseButton.Left))
            {
                switch (State)
                {
                    case ToolStateEnum.Picker:
                        Transform pickT = PickObject();
                        if (pickT != null)
                            traget = pickT;
                        break;
                }
            }
        }

        static public void OnRenderFrame()
        {
            if (traget != null)
            {
                switch (State)
                {
                    case ToolStateEnum.Picker:
                        DebugDrawer.instance.DrawBoundBox(traget.GetComponent<Render>(), new Vector3(1));
                        break;
                }
            }

        }
    }
}